﻿using AutoMapper;
using MediatR;
using ShineTech.Domain.Models.Kanbans;
using ShineTech.Domain.Models.Users;
using ShineTech.Domain.SeedWork;
using ShineTech.Web.Helpers;
using ShineTech.Web.Missons.Commands;
using ShineTech.Web.Users.Commands;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;


namespace ShineTech.Web.Users
{
    public class UserCommandHandler
        : IRequestHandler<CreateUserCommand, UserDTO>
        , IRequestHandler<UserByIdQuery, UserDTO>
        , IRequestHandler<UserByEmailQuery, UserDTO>
        , IRequestHandler<UserByFiltersQuery, IEnumerable<UserDTO>>
        , IRequestHandler<UserLoginCommand, UserTokenDTO>

    {
        private readonly IUnitOfWork _uow;
        private readonly IUserRepository _userRepository;
        private readonly IMapper _mapper;

        public UserCommandHandler(IUserRepository userRepository, IUnitOfWork uow, IMapper mapper)
        {
            _userRepository = userRepository;
            _uow = uow;
            _mapper = mapper;
        }


        public async Task<UserDTO> Handle(CreateUserCommand request, CancellationToken cancellationToken)
        {
            User user = new User(request.Name, request.Password, request.Email, request.Phone);
            _userRepository.Add(user);
            await _uow.CommitAsync(cancellationToken);
            return _mapper.Map<UserDTO>(user);
        }

        public async Task<UserDTO> Handle(UserByIdQuery request, CancellationToken cancellationToken)
        {
            User user = await _userRepository.FindOneAsync(new UserByIdSpecification(request.Id));
            return _mapper.Map<UserDTO>(user);
        }
        public async Task<UserDTO> Handle(UserByEmailQuery request, CancellationToken cancellationToken)
        {
            User user = await _userRepository.FindOneAsync(new UserByEmailSpecification(request.Eamil));
            return _mapper.Map<UserDTO>(user);
        }
        public async Task<IEnumerable<UserDTO>> Handle(UserByFiltersQuery request, CancellationToken cancellationToken)
        {
            IEnumerable<User> users = await _userRepository.FindAllAsync(new UsersByFiltersSpecification(request.Name ?? string.Empty));
            return _mapper.Map<IEnumerable<UserDTO>>(users);
        }

        public async Task<UserTokenDTO> Handle(UserLoginCommand request, CancellationToken cancellationToken)
        {

            User user = await _userRepository.FindOneAsync(new UserLoginSpecification(request.Email, request.Password));

            if (user == null)
            {
                throw CustomException.Exception("邮箱或密码错误");
            }

            var userDto = new UserDTO() { Email = user.Email, Id = user.Id, Name = user.Name, Phone = user.Phone };
            var token = TokenHelper.CreateToken(userDto);
            SessionServer.Save(user.Id, token);
            return new UserTokenDTO
            {
                Email = userDto.Email,
                Id = userDto.Id,
                Name = userDto.Name,
                Phone = userDto.Phone,
                Token = token
            };

        }
    }
}
